/**
 * This class represents a unit of a product.
 * Units have a name, factor and a child unit
 * So you can build a unit chain
 * 
 * @author Konrad Paumann
 * @author Bernhard Denner
 * @author Maximilian Csuk
 * 
 * $Revision$
 * $Date$
 * 
 */


public class Unit implements Displayable {
	private String name;
	private int factor;
	private Unit child = null;
	
	/**
	 * constructor
	 * @param name: Unit name
	 * @param factor: Unit factor
	 */
	public Unit(String name, int factor) {
		this.name = name;
		this.factor = factor;
	}
	
	/**
	 * constructor to create Unit with restore string containing Unit data
	 * 
	 * @param UnitLine restore string: "name:factor;name2:factor2;na...."
	 */
	public Unit(String UnitLine) {
		String[] UnitLineSplit = UnitLine.split(";");
		String[] UnitArgs = UnitLineSplit[0].split(":");

		name = UnitArgs[0];
		factor = Integer.parseInt(UnitArgs[1]);
		if (UnitLine.indexOf(";") + 1 < UnitLine.length())
			child = new Unit( UnitLine.substring( UnitLine.indexOf(";") + 1 ));
		else
			child = null;
	}
	
	/**
	 * 
	 * @param name
	 * @param factor
	 * @param child: which unit should be the child, used for adding units between two elements
	 */
	public Unit(String name, int factor, Unit child) {
		this.name = name;
		this.factor = factor;
		this.child = child;
	}
	
	/**
	 * 
	 * @param unitName
	 * @param unitFactor
	 * @param parentUnit: specifies the position of the new element in the chain
	 * @throws ProductException: if parentUnit was not found in the chain
	 */
	public void addUnit(String unitName, int unitFactor, String parentUnit) 
				throws ProductException {
		if (parentUnit == name) {	// check if current instance is unit we are looking for
			if (child != null)		// if unit has a child, alter the factor of the child
				child.factor /= unitFactor;	// rounding !!! no exact factors

			// add new Unit to the chain
			child = new Unit(unitName, unitFactor, child); 
		} else {
			if (child == null)  
				throw new ProductException("Elterneinheit " + parentUnit + " existiert nicht");

			// continue searching
			child.addUnit(unitName, unitFactor, parentUnit);
		}
	}
	
	/**
	 * 
	 * @param unitName
	 * @return Unit: returns the new child unit
	 * @throws ProductException: if unit wasn't found in the unit chain
	 */
	public Unit removeUnit(String unitName)
			throws ProductException {
		
		if (unitName == name) {
			if (child != null)
				child.factor *= factor;
			
			return child;
		} else {
			if (child == null)
				throw new ProductException("Einheit " + unitName + " existiert nicht");
			
			child = child.removeUnit(unitName);
			return this;
		}
	}
	
	/**
	 * 
	 * @param unitName
	 * @return factor: all factors of the units in the chain are multiplicated, till unit
	 * 				   with 'unitName' is reached.
	 * @throws ProductException: if unit wasn't found in the chain
	 */
	public int getFactor(String unitName) 
		throws ProductException {
		
		if (unitName == name)
			return factor;
		
		if (child == null)
			throw new ProductException("Einheit " + unitName + " existiert nicht");
		
		return factor * child.getFactor(unitName);
	}
	
	/**
	 * @return String: a printable String lists all units in the chain
	 */
	public String getDisplayString() {
		String msg = " ->" + factor + " " + name;
		if (child != null)
			return msg + child.getDisplayString();
		else
			return msg;
	}
	
	/**
	 * 
	 * @return String: a restore string containing all unit data
	 */
	public String save() {
		String msg = name + ":" + factor + ";";
		if (child != null)
			return msg + child.save();
		else
			return msg;
	}

	
}
